package org.example.controller;

import org.example.Imp.ExamServiceImp;
import org.example.Imp.TemplateServiceImp;
import org.example.Student_ExamService;
import org.example.TemplateService;
import org.example.domain.*;
import org.example.dto.ExamPaperDTO;
import org.example.pageParam.CommonData;
import org.example.vo.QuestionVO;
import org.example.vo.StudentExamAnswerVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@RequestMapping("/studentExam/")
public class ExamControllerS {
    @Autowired
    private TemplateServiceImp templateServiceImp;
    @Autowired
    private Student_ExamService student_examService;
    @Autowired
    private ExamServiceImp examServiceImp;
    @RequestMapping("myExams")
    public String myExams(Long filterCondition,HttpSession httpSession, Model model){
        Student loginStudent = (Student)httpSession.getAttribute("loginStudent");
        Map<String,Object> map = new HashMap<>();
        map.put("studentId",loginStudent.getId());
        if (filterCondition==null){
            map.put("filterCondition",1);
        }else {
            map.put("filterCondition",filterCondition);
        }
        List<Map<String,String>> result = examServiceImp.selectExamByStudentId(map);
        model.addAttribute("exams",result);
        String view = null;
        if (filterCondition==null){
           view = "studentExam/myExams";
        }else {
            view = "studentExam/myExams::#exam_table";
        }
        return view;
    }
    @RequestMapping("intoExam")
    @ResponseBody
    public Integer intoExam(Long examId,HttpSession httpSession){
        //首先需要判断当前考试是否能正常进行
        //判断考试是否结束 或则 已经完成考试
        Exam exam = examServiceImp.selectExamById(examId);
        Student loginStudent = (Student)httpSession.getAttribute("loginStudent");
        Student_Exam student_exam = student_examService.selectStudentExamByExamAndStudentId(examId, loginStudent.getId());
        //首先判断当前考试是时长考试 还是 区间考试
        if (exam.getDuration()!=null){
            //时长考试 当考试状态为已结束 并且 考生参考状态为已完成 就不能进入考试页面了
            if (exam.getStatus().equals("已结束") && student_exam.getStatus().equals("已完成")){
                return 1;//表示时长考试已经结束
            }
            if (exam.getStatus().equals("考试中") && student_exam.getStatus().equals("已完成")){
                return 4;
            }
        }
        if (exam.getDuration()==null){
            // 考试是否过期
            //有过期 正好为考试时间  未开始
            if (new Date().after(exam.getEnd_time())){//已过期
                //需要修改考试状态 因为我们设计定时器在创建考试的时候
                examServiceImp.updateExamStatus(examId,"已完成");
                return 2;//考卷已过期
            }
            if (new Date().before(exam.getStart_time())){
                return 3;//考试未开始
            }
            if (exam.getStatus().equals("考试中") && student_exam.getStatus().equals("已完成")){
                //提前交卷
                return 4;
            }
        }
        //到此为止 学生正常进入考试 需要修改考试状态 和 学生参考状态
        //有一个问题 如果是时长考试 当前学生参加考试 需要修改考试状态 那其他学生的当前考试状态也会被修改？？？？怎么办 不管了
        if (exam.getStatus().equals("未考试") ){
            examServiceImp.updateExamStatus(examId,"考试中");
        }
        if (student_exam.getStatus().equals("未考试")){
            student_examService.updateStudentStatus(examId,loginStudent.getId(),"考试中");
        }
        //判断学生考试是否超时（超时考试一定是第二次进入考试）
        if (student_exam.getStart_time()!=null){
            //因为进入考试后 学生的考试时间start_time就会发生改变
            if (exam.getDuration()!=null){
                //时长考试
                Integer duration = exam.getDuration();
                Date start_time = student_exam.getStart_time();//第一次进入考试的时间
                Date curr_time = new Date();
                long interval = curr_time.getTime() - start_time.getTime();
                int interval_minutes = (int)(interval/1000/60);
                if (duration<interval_minutes){
                    //超时  另外还需要修改一下考试 跟 学生的状态
                    //这里就有问题了  多次预数据库交互  其实可以用动态sal处理
//                    examServiceImp.updateExamStatus(exam.getId(),"已完成");
                    student_examService.updateStudentStatus(student_exam.getExam_id(), student_exam.getStudent_id(),"已完成");
                    student_examService.updateStudentEnd_time(student_exam.getExam_id(), student_exam.getStudent_id(),new Date(start_time.getTime() + duration*60*1000));
                    return 1;
                }
            }else {
                //区间考试
                Date curr_time = new Date();
                Date end_time = exam.getEnd_time();
                if (curr_time.after(end_time)){
                    examServiceImp.updateExamStatus(exam.getId(),"已完成");
                    student_examService.updateStudentStatus(student_exam.getExam_id(), student_exam.getStudent_id(),"已完成");
                    student_examService.updateStudentEnd_time(student_exam.getExam_id(), student_exam.getStudent_id(),exam.getEnd_time());
                    return 2;
                }
            }

        }
        return 0;
    }
    @RequestMapping("examPaga.html")
    public String examPage(Long examId,HttpSession httpSession,Model model){
        //考生正常进入当前考试页面  页面需要当前考试生成的试卷(生成试卷后就不需要预数据库交互了)
        //当前考试可能是动态模板  也可能 静态模板 （模板不同 导致 考卷名称不同）
        Exam exam = examServiceImp.selectExamById(examId);
        Student loginStudent = (Student)httpSession.getAttribute("loginStudent");
        Long template_id = exam.getTemplate_id();
        Template template = templateServiceImp.selectTemplateById(template_id);
        String templateType = template.getTemplateType();
        String currentStudentPagePath = CommonData.COMMON_EXAM_PATH+exam.getName()+"/";
        if (templateType.equals("静态模板")){
            currentStudentPagePath = currentStudentPagePath +CommonData.COMMON_STATIC_TEMPLATE_PAGE_NAME;
        }else {
            currentStudentPagePath = currentStudentPagePath+loginStudent.getCode()+"_"+loginStudent.getSname()+".txt";
        }
        List<QuestionVO> questionVOS = student_examService.generateExamPaper(currentStudentPagePath);
        //将学生的考试开始时间修改一下
        Student_Exam student_exam = student_examService.selectStudentExamByExamAndStudentId(examId, loginStudent.getId());
        if (student_exam.getStart_time()==null){
            student_exam.setStart_time(new Date());
            student_examService.updateStudentStart_time(examId,loginStudent.getId());
        }else {
            //响应给页面的缓存数据
            if (exam.getDuration()==null){
                student_exam.setStart_time(new Date());
            }
        }
        model.addAttribute("exam",exam);
        model.addAttribute("student",loginStudent);
        model.addAttribute("questions",questionVOS);
        //因为做了一个断线数据保存的处理 所以第二次进入这个页面需要考虑是否存在上一次填写的答案 然后解析
        StudentExamAnswerVO param = student_examService.parseExamAnswer(student_exam);
        model.addAttribute("answerVO",param);
        model.addAttribute("studentExam",student_exam);
        return "studentExam/enterExam";
    }
    private static Map<Long,Exam> examStatus = new HashMap<>();
    private static SimpleDateFormat SIMPLEDATEFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @ResponseBody
    @RequestMapping("examAnswerSave")
    public void examAnswerSave(@RequestParam Map<String,String> param){
        //如果一个学生在10分钟思考一道题 这10分钟都没有做答案选择 那保存就会浪费时间
        Student_Exam student_exam = student_examService.selectStudentExamByExamAndStudentId(Long.parseLong(param.get("examId")), Long.parseLong(param.get("studentId")));
        if (
                student_exam.getAnswer1()!=null && student_exam.getAnswer1().equals(param.get("question1_answer")) &&
                student_exam.getAnswer2()!=null && student_exam.getAnswer2().equals(param.get("question2_answer")) &&
                student_exam.getAnswer3()!=null && student_exam.getAnswer3().equals(param.get("question3_answer")) &&
                student_exam.getAnswer4()!=null && student_exam.getAnswer4().equals(param.get("question4_answer")) &&
                student_exam.getAnswer5()!=null && student_exam.getAnswer5().equals(param.get("question5_answer"))
        ){
            if (param.get("end_time")!=null){
                //处理考试卷子的客观题分数 单选 多选 填空
                examServiceImp.handleOneStudentExamPaperScore(student_exam);
                //最终保存 必须提交
                student_examService.examAnswerSave(param);//保存答案
                Long examId = Long.parseLong(param.get("examId"));
                Exam exam = examServiceImp.selectExamById(examId);
                if (examStatus.get(examId) == null){
                    //说明这个学生是这场考试的第一个提交的
                    examStatus.put(examId,exam);
                }
                student_examService.updateStudentStatus(Long.parseLong(param.get("examId")),Long.parseLong(param.get("studentId")),"已完成");
                Date student_exam_end_time = null;
                try {
                    student_exam_end_time = SIMPLEDATEFORMAT.parse(param.get("end_time"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (exam.getDuration()==null && exam.getEnd_time().getTime() == student_exam_end_time.getTime()){
                    //如果想要将区间考试的状态修改为已完成 必须要满足 考试为区间考试 并且 当前学生交卷的end_time等于考试的end_time
                    //如果很多学生同一考试结束时间提交 每一个学生都做一次考试状态的改变 冗余了 我们可以利用缓存 存储考试状态
                    Exam exam1 = examStatus.get(examId);
                    if (!exam1.getStatus().equals("已完成")){
                        //说明已经有学生改变过这场考试的状态了 不需要改变了
                        examServiceImp.updateExamStatus(examId,"已完成");
                        student_examService.finishExamToUpdateMissStatus(examId);
                        student_examService.finishExamToUpdateFinishStatus(examId);
                    }
                }
            }else {
                return;//这里有问题 因为前端如果没有这种类型的题 传过来为“” 数据库则是 null 应该在数据库存储是做一下处理 算了 我们按照正常都有的处理
            }
        }else {
            student_examService.examAnswerSave(param);
            if (param.get("end_time")!=null){
                //处理考试卷子的客观题分数 单选 多选 填空
                examServiceImp.handleOneStudentExamPaperScore(student_exam);
                //最终保存 必须提交
                student_examService.examAnswerSave(param);//保存答案
                Long examId = Long.parseLong(param.get("examId"));
                Exam exam = examServiceImp.selectExamById(examId);
                if (examStatus.get(examId) == null){
                    //说明这个学生是这场考试的第一个提交的
                    examStatus.put(examId,exam);
                }
                student_examService.updateStudentStatus(Long.parseLong(param.get("examId")),Long.parseLong(param.get("studentId")),"已完成");
                Date student_exam_end_time = null;
                try {
                    student_exam_end_time = SIMPLEDATEFORMAT.parse(param.get("end_time"));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                if (exam.getDuration()==null && exam.getEnd_time().getTime() == student_exam_end_time.getTime()){
                    //如果想要将区间考试的状态修改为已完成 必须要满足 考试为区间考试 并且 当前学生交卷的end_time等于考试的end_time
                    //如果很多学生同一考试结束时间提交 每一个学生都做一次考试状态的改变 冗余了 我们可以利用缓存 存储考试状态
                    Exam exam1 = examStatus.get(examId);
                    if (!exam1.getStatus().equals("已完成")){
                        //说明已经有学生改变过这场考试的状态了 不需要改变了
                        examServiceImp.updateExamStatus(examId,"已完成");
                        student_examService.finishExamToUpdateMissStatus(examId);
                        student_examService.finishExamToUpdateFinishStatus(examId);
                    }
                }
            }else {
                return;//这里有问题 因为前端如果没有这种类型的题 传过来为“” 数据库则是 null 应该在数据库存储是做一下处理 算了 我们按照正常都有的处理
            }
        }

    }
    @RequestMapping("studentExamResultList.html")
    public String studentExamResultList(HttpSession httpSession,Model model){
        Student student = (Student) httpSession.getAttribute("loginStudent");
        List<Integer> years = examServiceImp.selectStudentCurrYear(student.getId());
        //默认展示当前年份
        List<ExamPaperDTO> currYearExam = examServiceImp.selectExamByYear(student.getId(), years.get(0));
        model.addAttribute("years",years);
        model.addAttribute("currYearExams",currYearExam);
        return "studentExam/studentExamResult";
    }
    @RequestMapping("selectExamByYear")
    public String selectExamByYear(Integer year,HttpSession httpSession,Model model){
        Student student = (Student) httpSession.getAttribute("loginStudent");
        List<Integer> years = examServiceImp.selectStudentCurrYear(student.getId());
        //默认展示当前年份
        List<ExamPaperDTO> currYearExam = examServiceImp.selectExamByYear(student.getId(), year);
        model.addAttribute("years",years);
        model.addAttribute("currYearExams",currYearExam);
        return "studentExam/studentExamResult";
    }
}
